package com.ksyun.campus.client;

import org.apache.hc.client5.http.classic.HttpClient;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.HttpStatus;
import org.apache.hc.core5.http.io.entity.EntityUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;

public class FSInputStream extends InputStream {

    private final HttpClient httpClient;
    private final String filePath;
    private final String fileSystemName;
    private static final int CHUNK_SIZE = 1024 * 1024 * 10; // 10MB

    private byte[] buffer = new byte[0];
    private int bufferOffset = 0;
    private int bytesRead = 0;
    private long currentOffset = 0;
    private boolean endOfFileReached = false; // 标志位，用于标记文件是否已读完

    public FSInputStream(HttpClient httpClient, String filePath, String fileSystemName) {
        this.httpClient = httpClient;
        this.filePath = filePath;
        this.fileSystemName = fileSystemName;
    }

    @Override
    public int read() throws IOException {
        byte[] singleByte = new byte[1];
        int result = read(singleByte);
        return result == -1 ? -1 : singleByte[0] & 0xFF;
    }

    @Override
    public int read(byte[] b) throws IOException {
        return read(b, 0, b.length);
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        if (b == null) {
            throw new NullPointerException("The provided byte array is null");
        }
        if (off < 0 || len < 0 || (off + len > b.length)) {
            throw new IndexOutOfBoundsException("Array index out of range");
        }

        int totalBytesRead = 0;

        while (totalBytesRead < len) {
            // 如果缓冲区为空或耗尽，重新填充
            if (bufferOffset >= bytesRead) {
                if (endOfFileReached) {
                    // 如果已到达文件末尾，不再读取
                    break;
                }
                bytesRead = readChunk();
                if (bytesRead == -1) {
                    // 文件结束
                    break;
                }
                bufferOffset = 0;
            }

            int bytesToCopy = Math.min(len - totalBytesRead, bytesRead - bufferOffset);
            System.arraycopy(buffer, bufferOffset, b, off + totalBytesRead, bytesToCopy);
            bufferOffset += bytesToCopy;
            totalBytesRead += bytesToCopy;
        }

        return totalBytesRead > 0 ? totalBytesRead : -1;
    }

    private int readChunk() throws IOException {
        String encodedFilePath = URLEncoder.encode(filePath, StandardCharsets.UTF_8.toString());
        String encodedFileSystemName = URLEncoder.encode(fileSystemName, StandardCharsets.UTF_8.toString());

        String url = "http://localhost:9000/read"; // 实际的服务器地址
        String fullUrl = url + "?path=" + encodedFilePath + "&fileSystemName=" + encodedFileSystemName + "&offset=" + currentOffset + "&length=" + CHUNK_SIZE;

        System.out.println("Generated URL: " + fullUrl);

        HttpGet httpGet = new HttpGet(fullUrl);

        // 将 fileSystemName 添加到请求头
        httpGet.setHeader("fileSystemName", fileSystemName);

        // 发送请求并处理响应
        try (CloseableHttpResponse response = (CloseableHttpResponse) httpClient.execute(httpGet)) {
            int statusCode = response.getCode();
            if (statusCode == HttpStatus.SC_OK) {
                byte[] chunkData = EntityUtils.toByteArray(response.getEntity());
                if (chunkData.length > 0) {
                    buffer = chunkData;
                    currentOffset += chunkData.length; // 更新当前偏移量

                    // 如果接收到的数据块大小小于 CHUNK_SIZE，标记为文件末尾
                    if (chunkData.length < CHUNK_SIZE) {
                        endOfFileReached = true;
                    }

                    return buffer.length;
                } else {
                    endOfFileReached = true; // 接收到的数据块大小为0，标记文件末尾
                }
            }
        }

        return -1;
    }

    @Override
    public void close() throws IOException {
        super.close();
    }
}
